package com.hm.health.Activity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;

import com.goodix.activity.FileBrowserActivity;
import com.goodix.comsdk.entity.MeasureResult;
import com.goodix.comsdk.sdk.OnHBDDataListener;
import com.goodix.comsdk.testsdk.IHBDTestClient;
import com.goodix.http.jsonparams.request.UploadCfgInfoParams;
import com.goodix.libromablecom.sdk.cardiff.CardiffEvkConfigUtils;
import com.goodix.utils.DefaultSpUtil;
import com.goodix.utils.RawdataUtils;
import com.goodix.utils.SPUtils;
import com.goodix.widget.AlertDialogEx;
import com.goodix.libromablecom.sdk.cardiff.arguments.GetArgumentsKeyEnum;
import com.goodix.libromablecom.sdk.cardiff.arguments.SetArgumentsKeyEnum;
import com.hm.health.MyApplication;
import com.hm.health.R;
import com.hm.health.Utils.Constans;
import com.hm.health.Utils.FileLogUtil;
import com.hm.health.Utils.FileSaveHandler;
import com.hm.health.Utils.FileUtil;
import com.hm.health.adapter.DeviceConfigAdapter;
import com.hm.health.entity.DeviceConfigBean;
import com.hm.health.entity.arguments.StartArgumentsManager;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Created by chenshi on 2020/1/14.
 */

public class AlgorithmSimulationActivity extends BaseActivity{
    public static final String TAG = "AlgorithmSimulation";

    public static final int REQUEST_GET_OUT_DIR_PATH = 1;
    public static final int REQUEST_GET_INPUT_DIR_PATH = 2;
    private static final int REQUEST_GET_CFG_PATH = 3;

    public static final String ARG_ALGORITHM_PROGRESS = "ARG_ALGORITHM_PROGRESS";
    public static final String KEY_LAST_CFG_PATH = "key_last_cfg_path";
    private static Pattern pattern = Pattern.compile("\\d{4}-\\d{1,2}-\\d{1,2}-\\d{1,2}-\\d{1,2}-\\d{1,2}");
    public static final String KEY_LAST_SIMULATION_DIR_IN = "prefs_key_last_simulation_dir";
    public static final String KEY_LAST_SIMULATION_DIR_OUT = "prefs_key_last_simulation_out_dir";
    public static final String KEY_LAST_SIMULATION_SCENE_POSITION = "prefs_key_last_simulation_scene_id";
    public static final String KEY_LAST_SIMULATION_ALG_TYPE_POSITION = "key_last_simulation_alg_type_postion";

    @BindView(R.id.tv_input_data_path)
    TextView mTvInputDataPath;
    @BindView(R.id.tv_out_data_path)
    TextView mTvOutDataPath;
    @BindView(R.id.rv_file_list)
    RecyclerView mRvFileList;
    @BindView(R.id.btn_start)
    Button mBtnStart;
    @BindView(R.id.tv_cfg_path)
    TextView mTvCfgPath;
    @BindView(R.id.cb_use_default_cfg)
    CheckBox mCheckBoxUseDefaultCfg;
    @BindView(R.id.sp_scene)
    Spinner mSpScene;
    @BindView(R.id.cb_use_defalut_scene)
    CheckBox mCbUseDefaultScene;
    @BindView(R.id.sp_alg_lib_type)
    Spinner mAlgorithmLibType;

    private DeviceConfigAdapter mFileStateAdapter;
    private List<DeviceConfigBean> mFileStates = new ArrayList<>();

    private  ExecutorService mExecutorService;
    private DeviceConfigBean mCurrDeviceConfigBean;
    private String mSelectSceneName = "";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_algorithm_simulation);
        ButterKnife.bind(this);
        initActionBar(getString(R.string.algorithm_simulation));
        initView();
    }

    private void initView() {
        mFileStateAdapter = new DeviceConfigAdapter(mContext,
                mFileStates, R.layout.item_algorithm_simulation);
        mFileStateAdapter.showProgressBar(false);
        mRvFileList.setAdapter(mFileStateAdapter);
        mFileStateAdapter.notifyDataSetChanged();

        String path = DefaultSpUtil.getValue(mContext, KEY_LAST_SIMULATION_DIR_IN, "");
        mTvInputDataPath.setText(path);

        path = DefaultSpUtil.getValue(mContext, KEY_LAST_SIMULATION_DIR_OUT, "");
        mTvOutDataPath.setText(path);

        int position = DefaultSpUtil.getValue(mContext, KEY_LAST_SIMULATION_SCENE_POSITION, 0);
        if (position < mSpScene.getCount()) {
            mSpScene.setSelection(position);
        }

        // 算法库类型
        position = DefaultSpUtil.getValue(mContext, KEY_LAST_SIMULATION_ALG_TYPE_POSITION, 0);
        if (position < mAlgorithmLibType.getCount()) {
            mAlgorithmLibType.setSelection(position);
        }
    }

    @OnClick(R.id.rl_select_input_path)
    public void onBtnSrcDir(View view) {
        String lastBrowserPath = (String)SPUtils.get(mContext,
                KEY_LAST_SIMULATION_DIR_IN, Constans.GOODIXHBD_FOLDER);
        FileBrowserActivity.startBrowser(this, REQUEST_GET_INPUT_DIR_PATH,
                true, "", lastBrowserPath);
    }

    @OnClick(R.id.rl_select_out_path)
    public void onBtnDestDir(View view) {
        String lastBrowserPath = (String)SPUtils.get(mContext,
                KEY_LAST_SIMULATION_DIR_OUT, Constans.GOODIXHBD_FOLDER);
        FileBrowserActivity.startBrowser(this, REQUEST_GET_OUT_DIR_PATH,
                true, "", lastBrowserPath);
    }

    @OnClick(R.id.rl_select_drv_config_path)
    public void onBtnSelectDrvConfigPath(View v) {
        String lastBrowserPath = (String)SPUtils.get(mContext,
                KEY_LAST_CFG_PATH, Constans.GOODIXHBD_FOLDER);
        FileBrowserActivity.startBrowser(this, REQUEST_GET_CFG_PATH,
                false, "", lastBrowserPath);
    }

    @OnClick(R.id.btn_start)
    public void onBtnStart(View view) {
        if (null != mExecutorService) {
            mExecutorService.shutdownNow();
            mExecutorService = null;
        }

        for (DeviceConfigBean state : mFileStates) {
            state.setStatus(DeviceConfigBean.STATUS_READY);
        }
        mFileStateAdapter.notifyDataSetChanged();

        boolean useDefaultConfig = mCheckBoxUseDefaultCfg.isChecked();
        String drvCfgPath = mTvCfgPath.getText().toString();

        int selectScenePos = mSpScene.getSelectedItemPosition();
        DefaultSpUtil.put(mContext, KEY_LAST_SIMULATION_SCENE_POSITION, selectScenePos);

        // 算法库类型
        int algorithmLibType = mAlgorithmLibType.getSelectedItemPosition();
        DefaultSpUtil.put(mContext, KEY_LAST_SIMULATION_ALG_TYPE_POSITION, algorithmLibType);

        mSelectSceneName = (String) mSpScene.getSelectedItem();
        if (mCbUseDefaultScene.isChecked()) {
            mSelectSceneName = "";
        }

        mExecutorService = Executors.newSingleThreadScheduledExecutor();
        mExecutorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    runOnUiThread(() -> {
                        mBtnStart.setText(getString(R.string.cancel));
                        mBtnStart.setEnabled(false);
                    });

                    String path = mTvInputDataPath.getText().toString();

                    IHBDTestClient ihbdTestClient = MyApplication.getHBDTestClient();
                    ihbdTestClient.registerHBDDataListener(mOnHBDDataListener);

                    int cnt = 0;
                    for (DeviceConfigBean fileState : mFileStates) {
                        mCurrDeviceConfigBean = fileState;
                        Matcher matcher = pattern.matcher(fileState.getFileName());
                        String time = "";
                        if (matcher.find()) {
                            time = matcher.group();
                        }

                        // 文件路径
                        String absolutePath = path + "/" + fileState.getFileName();
                        Log.d(TAG, "file path: " + absolutePath);

                        // 设置测量模式
                        UploadCfgInfoParams params = RawdataUtils.getFileHeader(absolutePath);
                        if (null == params) {
                            runOnUiThread(() -> {
                                AlertDialogEx.Builder builder = new AlertDialogEx.Builder(mContext);
                                builder.setMessage(getString(R.string.failled_get_file_header));
                                builder.setPositiveButton(R.string.ok, null);
                                builder.show();
                            });
                            return;
                        }

                        StartArgumentsManager.getInstance().setFunctionName(params.getMeasurementMode());

                        String drvConfig = "";
                        String errMsg = "";
                        if (useDefaultConfig) {
                            drvConfig = params.getDriveConfig();
                            errMsg = getString(R.string.can_not_get_driver_config_from_raw_data);
                        } else {
                            drvConfig = CardiffEvkConfigUtils.getDriverConfig(drvCfgPath);
                            errMsg = getString(R.string.failed_get_driver_cfg_from_ini_file);
                        }

                        if ((null == drvConfig) || (drvConfig.isEmpty())) {
                            String finalMsg = errMsg;
                            runOnUiThread(() -> {
                                AlertDialogEx.Builder builder = new AlertDialogEx.Builder(mContext);
                                builder.setMessage(finalMsg);
                                builder.setPositiveButton(R.string.ok, null);
                                builder.show();
                            });
                            return;
                        }

                        fileState.setStatus(DeviceConfigBean.STATUS_SENDING);
                        FileSaveHandler fileSaveHandler = new FileSaveHandler();
                        // 设置存文件的场景、测试人信息
                        if (mSelectSceneName.isEmpty()) {
                            mSelectSceneName = params.getSceneId();
                        }
                        StartArgumentsManager.getInstance().setSceneName(mSelectSceneName);
                        MyApplication.getInstance().setSubjectName(params.getSubjectName());
                        String funName = StartArgumentsManager.getInstance().getFunctionName();
                        String outDir = mTvOutDataPath.getText().toString() + "/alg_simulation_result_" + funName;
                        fileSaveHandler.start(outDir, time, new ArrayList<>());

                        // 仿真测试时手动创建目标存储文件
                        Map<String, FileLogUtil> fileLogUtilMap = fileSaveHandler.getFileSaveUtilMap();
                        String outFileName = fileState.getFileName().replace(".csv", "_result.csv");
                        outFileName = String.format("%s-%s-%s", funName, mSelectSceneName, outFileName);

                        // 删除已存在的文件
                        String outAbsoulateFilePath = String.format("%s/%s", outDir, outFileName);
                        if (new File(outAbsoulateFilePath).exists()) {
                            FileUtil.deleteFile(outAbsoulateFilePath);
                        }

                        FileLogUtil fileLogUtil = new FileLogUtil(outDir, outFileName);
                        fileLogUtilMap.put(funName, fileLogUtil);
                        fileLogUtil.startSave();

                        // 文件头
                        BufferedReader reader = null;
                        try {
                            reader = new BufferedReader(new FileReader(absolutePath));
                            String header = reader.readLine();
                            fileLogUtil.saveData(header + "\n");
                            header = reader.readLine();
                            fileLogUtil.saveData(header + "\n");
                            reader.close();
                        } catch (Exception e) {
                            try {
                                if (null != reader) {
                                    reader.close();
                                }
                            } catch (Exception ex) {}
                            Log.e(TAG, "run: ", e.getCause());
                            return;
                        }

                        // 设置仿真场景
                        int algSceneId = StartArgumentsManager.getInstance().getSceneId();
                        ihbdTestClient.setRunTimeFlag(SetArgumentsKeyEnum.ARG_ALG_SIMULATION_ALGORITHM_SCENE, String.valueOf(algSceneId));
                        // 设置驱动配置文件
                        ihbdTestClient.setRunTimeFlag(SetArgumentsKeyEnum.ARG_SET_DRIVER_CFG_DATA, drvConfig);
                        // 设置仿真文件输出目录
                        ihbdTestClient.setRunTimeFlag(SetArgumentsKeyEnum.ARG_ALG_SIMULATION_OUT_DIR, outDir);
                        // 设置仿真输入文件路径
                        ihbdTestClient.setRunTimeFlag(SetArgumentsKeyEnum.ARG_START_ALGORITHM_SIMULATION, absolutePath);
                        // 算法库类型
                        ihbdTestClient.setRunTimeFlag(SetArgumentsKeyEnum.ARG_ALG_SIMULATION_LIB_SELECT, String.valueOf(algorithmLibType));
                        // 开始仿真
                        String result = ihbdTestClient.getRunTimeFlag(GetArgumentsKeyEnum.ARG_GET_ALGORITHM_SIMULATION_RESULT);
                        fileSaveHandler.stop();

                        if (!result.toUpperCase().equals(Constans.SUCCESS)) {
                            runOnUiThread(() -> {
                                fileState.setStatus(DeviceConfigBean.STATUS_ERROR);
                                mFileStateAdapter.notifyDataSetChanged();
                                AlertDialogEx.Builder builder = new AlertDialogEx.Builder(mContext);
                                String msg = result;
                                if (msg.isEmpty()) {
                                    msg = "Return value is Empty!";
                                }
                                builder.setMessage(msg);
                                builder.setPositiveButton(R.string.ok, null);
                                builder.show();
                            });
                            return;
                        } else {
                            fileState.setStatus(DeviceConfigBean.STATUS_SUCCESS);
                            runOnUiThread(() -> {
                                if (cnt - 5 > 0) {
                                    mRvFileList.smoothScrollToPosition(cnt - 5);
                                }
                                mFileStateAdapter.notifyDataSetChanged();
                            });
                        }
                    }
                    ihbdTestClient.unRegisterHBDDataListener(mOnHBDDataListener);

                } finally {
                    runOnUiThread(() -> {
                        mBtnStart.setText(getString(R.string.start));
                        mBtnStart.setEnabled(true);
                    });
                }
            }
        });
    }

    OnHBDDataListener mOnHBDDataListener = new OnHBDDataListener() {
        @Override
        public void onDataChanged(String dataType, int[] dataArr) {
//            if (dataType.equals(ARG_ALGORITHM_PROGRESS)) {
//                if (null != mCurrDeviceConfigBean) {
//                    mCurrDeviceConfigBean.setProgress(dataArr[0]);
//                }
//                runOnUiThread(() -> mFileStateAdapter.notifyDataSetChanged());
//            }
        }

        @Override
        public void onMeasureResult(MeasureResult result) {

        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }

        String iniFilePath;
        switch (requestCode) {
            case REQUEST_GET_INPUT_DIR_PATH:
                iniFilePath = data.getStringExtra(FileBrowserActivity.EXTRA_KEY_PATH);
                mTvInputDataPath.setText(iniFilePath);
                updateFileList(iniFilePath);
                SPUtils.put(mContext, KEY_LAST_SIMULATION_DIR_IN, iniFilePath);
                break;
            case REQUEST_GET_OUT_DIR_PATH:
                iniFilePath = data.getStringExtra(FileBrowserActivity.EXTRA_KEY_PATH);
                mTvOutDataPath.setText(iniFilePath);
                SPUtils.put(mContext, KEY_LAST_SIMULATION_DIR_OUT, iniFilePath);
                break;
            case REQUEST_GET_CFG_PATH:
                iniFilePath = data.getStringExtra(FileBrowserActivity.EXTRA_KEY_PATH);
                mTvCfgPath.setText(iniFilePath);
                SPUtils.put(mContext, KEY_LAST_CFG_PATH, iniFilePath);
                break;
            default:
                break;
        }
    }


    private void updateFileList(String filePath) {

        mFileStates.clear();
        mFileStateAdapter.notifyDataSetChanged();

        File dir = new File(filePath);
        if (!dir.exists()) { return;}

        String[] names = dir.list((file, s) -> s.endsWith(".csv"));
        if (null == names || names.length == 0) {
            return;
        }

        int cnt = 0;
        for (String name : names) {
            mFileStates.add(new DeviceConfigBean(cnt++, name));
        }

        mFileStateAdapter.notifyDataSetChanged();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != mExecutorService) {
            mExecutorService.shutdownNow();
        }
    }
}
